//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using OpenLS.Core.Serialization;

namespace OpenLS.Spreadsheet.Data
{
    public abstract partial class DataConnection: IOfficeXmlSerializable
    {
        public DataConnection()
        {
            Initialize();
        }

        internal abstract void Initialize();

        #region IOfficeXmlSerializable Members

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            using (ReadContext c = context.Read("connection"))
            {
                ReadAttributes(c);
                ReadProperties(c);
                ReadEnd(c);
            }
        }

        private void ReadEnd(ReadContext c)
        {
            Parameters.Clear();
            foreach (ConnectionParameter p in c.ReadOptionalListElement<ConnectionParameter>("parameters", "parameter"))
                Parameters.Add(p);
            Extension = c.ReadOptionalElement<ExtensionElement>("extLst");
        }

        private void ReadAttributes(ReadContext c)
        {
            Id = c.GetUIntegerAsInteger("id");
            SourceFile = c.GetOptionalString("sourceFile");
            OdcFile = c.GetOptionalString("odcFile");
            KeepAlive = c.GetOptionalBoolean("keepAlive", false);
            Interval = c.GetOptionalUIntegerAsInteger("interval", 0);
            Name = c.GetOptionalString("name");
            Description = c.GetOptionalString("description");
            Type = (DataConnectionType)c.GetOptionalUIntegerAsInteger("type", 0);
            ReconnectionMethod = c.GetOptionalUIntegerAsInteger("reconnectionMethod", 1);
            RefreshedVersion = c.GetInteger("refreshedVersion");
            MinRefreshableVersion = c.GetOptionalInteger("minRefreshableVersion", 0);
            SavePassword = c.GetOptionalBoolean("savePassword", false);
            IsNew = c.GetOptionalBoolean("new", false);
            IsDeleted = c.GetOptionalBoolean("deleted", false);
            OnlyUseConnectionFile = c.GetOptionalBoolean("onlyUseConnectionFile", false);
            Background = c.GetOptionalBoolean("background", false);
            RefreshOnLoad = c.GetOptionalBoolean("refreshOnLoad", false);
            SaveData = c.GetOptionalBoolean("saveData", false);
            Credentials = c.GetOptionalEnum<CredentialsMethod>("credentials", CredentialsMethod.Integrated);
            SingleSignOnId = c.GetOptionalString("singleSignOnId");
        }

/*        internal void ReadProperties(ReadContext c)
        {
            DatabaseProperties = c.ReadOptionalElement<DatabaseConnectionProperties>("dbPr");
            OlapProperties = c.ReadOptionalElement<OlapConnectionProperties>("olapPr");
            WebQueryProperties = c.ReadOptionalElement<WebQueryConnectionProperties>("webPr");
            TextProperties = c.ReadOptionalElement<TextConnectionProperties>("textPr");
        }
        */
        internal abstract void ReadProperties(ReadContext context);
        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            using (WriteContext c = context.Write("connection"))
            {
                c.SetUIntegerAsInteger("id", Id);
                c.SetOptionalString("sourceFile", SourceFile);
                c.SetOptionalString("odcFile", OdcFile);
                c.SetOptionalBoolean("keepAlive", KeepAlive, false);
                c.SetOptionalUIntegerAsInteger("interval", Interval, 0);
                c.SetOptionalString("name", Name);
                c.SetOptionalString("description", Description);
                c.SetUIntegerAsInteger("type", (int)Type);
                c.SetOptionalUIntegerAsInteger("reconnectionMethod", ReconnectionMethod, 1);
                c.SetInteger("refreshedVersion", RefreshedVersion);
                c.SetOptionalInteger("minRefreshableVersion", MinRefreshableVersion, 0);
                c.SetOptionalBoolean("savePassword", SavePassword, false);
                c.SetOptionalBoolean("new", IsNew, false);
                c.SetOptionalBoolean("deleted", IsDeleted, false);
                c.SetOptionalBoolean("onlyUseConnectionFile", OnlyUseConnectionFile, false);
                c.SetOptionalBoolean("background", Background, false);
                c.SetOptionalBoolean("refreshOnLoad", RefreshOnLoad, false);
                c.SetOptionalBoolean("saveData", SaveData, false);
                c.SetOptionalEnum<CredentialsMethod>("credentials", Credentials, CredentialsMethod.Integrated);
                c.SetOptionalString("singleSignOnId", SingleSignOnId);
                WriteProperties(c);
                if (Parameters.Count > 0)
                {
                    using (WriteContext c2 = c.Write("parameters"))
                    {
                        foreach (ConnectionParameter p in Parameters)
                            c2.WriteElement(p);
                    }
                }
                c.WriteOptionalElement(Extension);
            }
        }

        internal abstract void WriteProperties(WriteContext context);

        #endregion

        private ExtensionElement _extension;

        public ExtensionElement Extension
        {
            get { return _extension; }
            set { _extension = value; }
        }
        
        private List<ConnectionParameter> parameters = new List<ConnectionParameter>();

        public List<ConnectionParameter> Parameters
        {
            get { return parameters; }
            set { parameters = value; }
        }
        private int _id = Math.Abs(Guid.NewGuid().GetHashCode());

        internal int Id
        {
            get { return _id; }
            set { _id = value; }
        }
        private string _sourceFile;

        public string SourceFile
        {
            get { return _sourceFile; }
            set { _sourceFile = value; }
        }
        private string odcFile;

        public string OdcFile
        {
            get { return odcFile; }
            set { odcFile = value; }
        }
        private bool keepAlive;

        public bool KeepAlive
        {
            get { return keepAlive; }
            set { keepAlive = value; }
        }
        private int interval;

        public int Interval
        {
            get { return interval; }
            set { interval = value; }
        }
        private string name = Guid.NewGuid().ToString();

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private string description;

        public string Description
        {
            get { return description; }
            set { description = value; }
        }
        private DataConnectionType _type;

        public DataConnectionType Type
        {
            get { return _type; }
            set { _type = value; }
        }
        private int reconnectionMethod = 1;

        public int ReconnectionMethod
        {
            get { return reconnectionMethod; }
            set { reconnectionMethod = value; }
        }
        private int refreshedVersion;

        public int RefreshedVersion
        {
            get { return refreshedVersion; }
            set { refreshedVersion = value; }
        }
        private int minRefreshableVersion;

        public int MinRefreshableVersion
        {
            get { return minRefreshableVersion; }
            set { minRefreshableVersion = value; }
        }
        private bool savePassword;

        public bool SavePassword
        {
            get { return savePassword; }
            set { savePassword = value; }
        }
        private bool _new;

        public bool IsNew
        {
            get { return _new; }
            set { _new = value; }
        }
        private bool deleted;

        public bool IsDeleted
        {
            get { return deleted; }
            set { deleted = value; }
        }
        private bool onlyUseConnectionFile;

        public bool OnlyUseConnectionFile
        {
            get { return onlyUseConnectionFile; }
            set { onlyUseConnectionFile = value; }
        }
        private bool _background;

        public bool Background
        {
            get { return _background; }
            set { _background = value; }
        }
        private bool _refreshOnLoad;

        public bool RefreshOnLoad
        {
            get { return _refreshOnLoad; }
            set { _refreshOnLoad = value; }
        }
        private bool _saveData;

        public bool SaveData
        {
            get { return _saveData; }
            set { _saveData = value; }
        }
        private CredentialsMethod credentials = CredentialsMethod.Integrated;

        public CredentialsMethod Credentials
        {
            get { return credentials; }
            set { credentials = value; }
        }
        private string singleSignOnId;

        public string SingleSignOnId
        {
            get { return singleSignOnId; }
            set { singleSignOnId = value; }
        }

        internal static DataConnection ReadConnection(ReadContext context)
        {
            DataConnection result = null;
            DataConnectionType type = (DataConnectionType)context.GetOptionalInteger("type", 0);
            switch (type)
            {
                case DataConnectionType.Dao:
                    result = new DaoConnection(); break;
                case DataConnectionType.Text:
                    result = new TextConnection(); break;
                case DataConnectionType.WebQuery:
                    result = new WebQueryConnection(); break;
            }
            result = null;
            ConnectionAttributes a = new ConnectionAttributes();
            a.ReadAttributes(context);
            using (ReadContext c = context.Read("connection"))
            {
                if (c.ReaderLocalName == "dbPr")
                {
                    result = ReadProperties<DatabaseConnection>(c);
                }
                if (c.ReaderLocalName == "olapPr")
                {
                    result = readAndCombine<OlapConnection>(c, result);
                }
                if (c.ReaderLocalName == "webPr")
                {
                    result = readAndCombine<WebQueryConnection>(c, result);
                }
                if (c.ReaderLocalName == "textPr")
                {
                    result = readAndCombine<TextConnection>(c, result);
                }
                if (result == null)
                    result = new EmptyConnection();
                a.CopyTo(result);
                result.SetTypeIfNecessary();
                result.ReadEnd(c);
                return result;
            }
        }
        static T ReadProperties<T>(ReadContext c) where T : DataConnection, new()
        {
            T result = new T();
            result.ReadProperties(c);
            return result;
        }
        static DataConnection readAndCombine<T>(ReadContext c, DataConnection other) where T : DataConnection, new() 
        {
            T result = ReadProperties<T>(c);
            if (other != null)
                return new ComplexConnection(result, other); 
            return result;
        }
        internal abstract void SetTypeIfNecessary();
    }
}
